Discussion Replacing INKEY() with INKEY.BIN By KENNETH N. GETZ AND KAREN ROBINSON As you may be aware, in dBASE III PLUS version 1.1, the INKEY() function does not trap Leftarrow. For this reason, Inkey.BIN was written to replace INKEY() in those instances where you want to trap the Leftarrow key. Inkey.BIN is an assembly language routine that checks the keyboard buffer to see if a key is pressed. If so, it reads the key from the buffer and translates it to a code you can as you would the code returned by INKEY(). There are, however, some differences between Inkey.BIN and INKEY(). The following list summarizes the similarities and the differences. 1. It supports the same keys INKEY() does in addition to the Leftarrow key. 2. Inkey.BIN operates similarly to INKEY() when INKEY() is used with SET ESCAPE OFF. Even if you SET ESCAPE ON, pressing Esc returns CHR(27) and does not terminate execution of your program. 3. Inkey.BIN returns the ASCII character corresponding to the correct INKEY() value instead of returning the actual numeric value. This is done since it is difficult to pass a numeric value to and from a LOADed module. When you use Inkey.BIN, for example, it returns a CHR(23) when you press Ctrl-W. In contrast, INKEY() returns a value of 23 for the same key press. To retain compatibility with INKEY(), use the ASC() function to convert the character value that Inkey.BIN returns to a numeric value. 4. INKEY() returns the values -1 through -9 for F2 through F10. Since Inkey.BIN returns characters instead of values, it adds 256 to the expected return value for function keys F2 through F10, as shown in the table below: Key INKEY() Inkey.BIN F1 28 28 F2 -1 255 F3 -2 254 F4 -3 253 F5 -4 252 F6 -5 251 F7 -6 250 F8 -7 249 F9 -8 248 F10 -9 247 In view of this difference, we suggest that you create memory variables for the function keys F2 through F10, using the Inkey.BIN values shown above. Then refer to them by name instead of by their numeric values. This makes them easier to modify should you need to change these values. For example, F1 = 28 F2 = 255 F3 = 254 . . . 5. Inkey.BIN waits in a long loop (65535 executions) for you to press a key. Without this loop key presses may be missed, requiring you to press the key several times before it registers. With the loop, Inkey.BIN never misses any key presses, but this does present a limitation. If no key is pressed, Inkey.BIN waits for one to six seconds (on an IBM XT, shorter on an AT) before it returns to dBASE III PLUS. This means: - Inkey.BIN is fine for applications where the program is to stop and wait for a keystroke, process it, and then go on from there. - The INKEY() function is better for applications like Cbmenu.PRG on the dBASE III PLUS Samples disk, where it is used to test for a pressed key, updating the clock if no key is pressed. With Inkey.BIN, the clock is updated only about once every six seconds. Setup Setup To setup Inkey.BIN create the text file, Inkey.ASM, using MODIFY COMMAND or any text editor that writes to standard ASCII text files. Then, assemble Inkey.ASM to a .BIN file. Before you begin, be sure that the following files are present, either in the same subdirectory as Inkey.ASM or through the DOS PATH command: MASM.EXE, LINK.EXE, and EXE2BIN.EXE. Follow the steps below to assemble Inkey.ASM as a .BIN file: 1. From the DOS prompt enter, MASM Inkey.ASM; This creates an object file (INKEY.OBJ). 2. Enter, LINK INKEY; This creates INKEY.EXE. 3. To create a .BIN file enter, EXE2BIN INKEY 4. Last, delete INKEY.EXE, ERASE INKEY.EXE Usage Usage To use Inkey.BIN, first LOAD it into memory. Then initialize a return variable to a value never used by Inkey.BIN. The example below uses CHR(200), although you may use any number between 128 and 246. You cannot, however, use CHR(0) to test if there is a key in the keyboard buffer since dBASE III PLUS cannot pass this value as the argument of CALL command. Finally, CALL it from within a DO WHILE keytrap loop. As stated before, if you want to evaluate the returned value using the values returned by INKEY(), use the ASC() function to convert the character to its numeric equivalent. The following programs show the programming differences between INKEY() and Inkey.BIN: With INKEY() With Inkey.BIN ------------ -------------- SET ESCAPE OFF LOAD Inkey SET TALK OFF SET TALK OFF x = 0 x = CHR(200) DO WHILE x = 0 DO WHILE x = CHR(200) x = INKEY() CALL Inkey WITH x ENDDO ENDDO ? "INKEY(): " + STR(x,3,0) ? "Inkey.BIN: " + STR(ASC(x),3,0) Program ; Program ...: Inkey.ASM ; Author ....: Kenneth N. Getz ; Date ......: April 1, 1987 ; ; .BIN file to be loaded from within dBASE III PLUS to replace the ; INKEY() function, since Version 1.1 doesn't trap left arrow correctly. ; The only differences are in the calling sequence (x = CHR(200), ; DO WHILE x = CHR(200)), in the return values (INKEY() returns an ; integer, Inkey.BIN returns a character), and in the use of function keys: ; ; KEY INKEY() INKEY.BIN ; --- ------- --------- ; F1 28 28 ; F2 -1 255 ; F3 -2 254 ; F4 -3 253 ; F5 -4 252 ; F6 -5 251 ; F7 -6 250 ; F8 -7 249 ; F9 -8 248 ; F10 -9 247 ; ; CODE SEGMENT BYTE PUBLIC 'CODE' INKEY PROC FAR ASSUME CS:code START: JMP ENTRY DELAY DW 0FFFFH TABLE DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 DB 0, 0, 0, 0, 15, 16, 17, 18, 19, 20 DB 21, 22, 23, 24, 25, 0, 0, 0, 0, 30 DB 31, 32, 33, 34, 35, 36, 37, 38, 0, 0 DB 0, 0, 0, 44, 45, 46, 47, 48, 49, 50 DB 0, 0, 0, 0, 0, 0, 0, 0, 28,255 DB 254,253,252,251,250,249,248,247, 0, 0 DB 1, 5, 18, 0, 19, 0, 4, 0, 6, 24 DB 3, 22, 7, 84, 85, 86, 87, 88, 89, 90 DB 91, 92, 93, 94, 95, 96, 97, 98, 99,100 DB 101,102,103,104,105,106,107,108,109,110 DB 111,112,113,114, 26, 2, 23, 30, 29, 31 DB 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 DB 31, 31 ENTRY: PUSH AX ; Save the registers used. PUSH CX MOV CX,DELAY ; Set up for wait loop. TOP: MOV AH,1 ; Set for buffer poll. INT 16H ; See if key in buffer. JNZ FOUND ; If so, jump out. LOOP TOP ; Otherwise, try again DELAY times. FOUND: JZ EXIT ; Quit if all the way through the loop. AND AH,0 ; Otherwise, set for buffer read. INT 16H ; Read the key from the buffer. CMP AL,0 ; See if we got an extended character. JNE ENDIT ; If not, we're OK. PUSH BX ; Otherwise, save BX for later. PUSH DS ; Save DS for dBASE III PLUS. PUSH CS ; Make CS and DS same for translation. POP DS MOV AL,AH ; Move extended value into AL. LEA BX,TABLE ; Get the address of the table. DEC AL ; Subtract 1 to offset at 0. XLAT ; Do the lookup. Answer in AL. POP DS ; Reset DS. POP BX ; Reset BX. ; Send back character to dBASE III PLUS. ENDIT: MOV BYTE PTR [BX],AL EXIT: POP CX ; Restore used registers. POP AX RET INKEY ENDP CODE ENDS END START